Display List

← Zurück zum Forum

An diesem Thema kommt man ja nicht vorbei und sollte es vermutlich auch früh verstehen, scheint mir eine Grundlage für alles weitere zu sein.

Der Empfehlung folgend habe ich alle Posts dieses Forenbereichs "durchgearbeitet" (so viele sind es ja zum Glück nicht). Ich gebe zu, vieles habe ich überflogen, einiges davon intensiver wie z.B. https://abbuc.de/forum/viewtopic.php?f=7&t=109 und auch Videos dazu angeschaut wie z.B. https://www.youtube.com/watch?v=io4AZmT9Bnw. Ob Deutsch oder Englisch ist mir persönlich egal.

Dennoch habe ich noch nichts zustande bekomme und brauche bitte etwas Eure Hilfe zur Einordnung.

a) Ist die Display-List abhängig von PAL/NTSC? Oder egalisiert die Hardware das, sodass am Ende effektiv immer dieselben Auflösungen heraus kommen? Vermutlich muss ich mir darüber keine Gedanken machen, denn etwas anderes als PAL werde ich kaum nutzen. Finde aber die Frage trotzdem interessant.

b) Es ist die Rede von einem Hardware-Treiber, also ein Stück Software zwischen der Anwendung und dem Grafik-Chip. Dieser ist wohl im ROM enthalten. Dieses ROM ist ja normalerweise aktiviert (habe Tricks gelesen das abzuschalten um mehr Speicher zu bekommen) und man könnte es auch von Assembler-Programmen aus nutzen, nehme ich an? Es wird also Einsprungpunkte für bestimmte Routinen geben, z.B. sowas wie einen DRAW oder FILL. Nutzt man sowas, oder ignoriert man diese Routinen und macht seine eigenen? Würde man in einem Arcade-Spiel überhaupt sowas wie DRAW, PLOT, FILL verwenden, oder nicht eher Tiles/Sprites? Bei letzterem wäre es ja praktisch egal ob es im ROM Routinen dafür gibt.

c) Es gibt ja zwei Video-Chips im Atari, den ANTIC und den GTIA. Wie hängt das mit der DLIST zusammen?

d) Sehe ich das richtig, das ich für mich definieren muss wie die Display-List aufgebaut, also mein Bildschirm aufgeteilt ist? So gesehen gäbe es also keine Default-DLIST. Ich würde also, nachdem ich mich für etwas entschieden habe, eine DLIST als Byte-Record in meinem Code hinterlegen

dlist    .byte 112, 112, 112, ...

und dann am Anfang meines Programmes den ANTIC auf diese DLIST einstellen, über die Register DLISTH/L ($D402,$D403):

DLSTL=$D402
DLSTH=$D403
start   lda #>dlist
    sta DLSTL
    lda #<dlist
    sta DLSTH

Danach würde ich dann irgendwie mit dem darin referenzierten Grafik-RAM arbeiten.

Generell stelle ich mir aber jetzt die Frage was ich damit anfangen soll? 😉 Ich würde ja gern einfach mal was auf den Bildschirm zaubern, einen Sternenhimmel z.B.

Wäre nicht die allereinfachste DLIST eine die nur aus einem oder mehreren BLANK lines besteht und damit den Bildschirm in der eingestellten Hintergrundfarbe zeichnet?

Hi,

1) Du schreibst die Adresse Deiner DisplayList in die Hardware-Register für die Displaylist Meines Wissens ist es aber so, daß solange der Atari mit normalem OS läuft, die laufenden Routinen des OS die Adresse der DisplayList aus den Schattenregistern in die Hardwareregister schreiben, und zwar (bei PAL) 50x pro Sekunde. Das heißt, wenn Du was in die Hardwareregister schreibst hast Du maximal eine 50tel Sekunde Zeit, Dein Arbeitsergebnis zu betrachten. Du müßtest also die Werte in die zuständigen Schattenregister eintragen. (Die 50x pro Sekunde laufende Prozedur nennt sich Vertical Blank Interrupt und den gibt es in 2 Wichtigkeitsstufen, immediate und deferred).

2) Zum Unterschied zwischen ANTIC und GTIA Grob gesagt bearbeitet der eine die Grafik im Arbeitsspeicher und der andere macht daraus ein Videosignal. Das ist aber nur sehr grob betrachtet.

3) Die DisplayList gibt an, in welcher Form der Arbeitsspeicher auf dem Bildschirm darzustellen ist. Allerdings muß auch noch angegeben werden, wo die Daten stehen, die angezeigt werden sollen. Das geschieht mit einem LoadMemoryScan (LMS) Eintrag. Und am Ende der Displaylist muß ein Jump-Befehl hin der darauf zeigt, wo als nächstes mit der DisplayList weiter gearbeitet werden soll. Das ist in der Regel der Anfang der DisplayList.

Wenn Du nun eine einfache DL erzeugt hast (z.B. 3 Leerzeichen und eine GR0 Zeile mit LMS und Du hast zuvor was in die Speicheradressen reingeschrieben, auf die LMS zeigt dann sollte da auch was auf dem Bildschirm erscheinen - vorausgesetzt die DL Adresse steht dann auch in den Schattenregistern.

Hab ich übrigens gerade so ausprobiert (im Debugger). Hat funktioniert. Wenn man da jetzt Text in der GR0 Zeile sehen will muß man die Bytes im Speicher allerdings im Bildschirmcode ablegen. Für "ABCD" also die Bytefolge $21,$22,$23,$24.

CU, Erhard

Jede Info, die zu Hause auf meinem Rechner liegt habe ich unterwegs nicht verfügbar. Jede Info, die im Netz liegt finde ich nicht wieder, wenn ich sie benötige.

Die Display List macht bei PAL und NTSC eher keine Probleme. Nutzt Du allerdings DLI oder VBI, kann das schon problematischer werden.

Allerdings gibt es gerade bei alten Fernsehern, das Problem, dass NTSC TV weniger darstellen können, als PAL TV. Daher hatte ATARI normalerweise immer 3 (8) komplette Leerzeilen in den Standard Grafikmodi verwendet ($70 bzw. 112) am Anfang jeder DL. Somit sollte jede Rechner/TV Kombination alles anzeigen können, was oben genauso gebaut ist und nach unten halt maximal 24 (8) Zeilen hoch ist.

Bis zu 30(*8) (also 240 einzelne Zeilen) ist am Atari möglich und moderne TV haben damit auch kein Problem.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

... hallo yMoreT8,

ich hatte dir ja eine einfache Beispiel-DL gepostet. In deinem Beispiel hast du Fehler drin: Nimm nicht die Hardwareregister $D402/03 sondern besser die Schattenregister $230/31 lda #>dlist holt den High-Byte-Wert von dlist und schreibt mit sta dlstl in den Low-Byte-Wert des Registers ein und umgekehrt. Das kann ja nicht funktionieren.

Die Displaylist ist übrigens zunächst etwas kompliziert erscheinend, birgt aber echt coole Möglichkeiten, wo unser kleiner Atari anderen Rechnern deutlich überlegen war. Die Displaylist ist quasi eine kleine Programmroutine, die der Antic abarbeitet. Dem Antic muss ich natürlich sagen, wo diese Routine im Speicher steht, das mache ich mit den Anweisungen lda #dlist / sta dlsth Nun weiß der Antiv, wo diese Routine steht und arbeitet die Befehle ab: Die drei 112 Anweisungen braucht es nicht zwingend. Hier wird der schwarze Balken am oberen Rand erzeugt, was füher bei den Röhrenmonitoren für den Overscan nötig war. Brauchst du mehr Platz, kannst du das auch weglassen... einfach mal damit experimentieren. Danach kommt der Befehl $40 (64). Dieser Befehl (echt verwirrend am Anfang) sagt dem Antic, wo der eigentliche Bildschirm im Coputerspeicher startet. Hinter dem $40 kommt also zunächst der Low-/ dann der Highbyte - Wert des Startbildschirmes im Speicher - oft an $9c40 (40000). Danach kommen x-Werte - nämlich die Anzahl der Zeilen je nach Grafikmodus, die Zahlen selber entscheiden über den jeweilige Grafikmodus. Will ich z.B. Graphics 0 haben (Antic 2 - die Nomenklatur weicht zu Basic ab), dann nehem ich also 23x 2 für 24 Zeilen. Dabei kommt jetzt ein echt unnötiger Zusatz: die erste Zeile wird direkt noch dem Befehl $40 mitgegeben - also $40+2 = $42 !! Man kann so übrigens auch fast beliebig die entsprechenden Grafikstufen Zeile für Zeile anders gestalten. Das macht das System so schön flexibel. Ganz am Ende kommt dann mit $41 (65) ein letzter Befehl - der Sprungbefehl mit enstprechender Adresse - nämlich den Anfang dieser kleinen Routine.

Ein sehr großer Vorteil dieses Aufbaus ist, daß man u.a. mit einer einzigen kleinen Speicheränderung den gesamten Bildschirm bewegen kann - im Maximum 8 kB zeitlos...

Wenn du Fragen hast, dann frag!

LG Peter

Hallo Peter,

Dr. Irata schrieb: Danach kommt der Befehl $40 (64).

soweit ich weiß steht die $40 nicht alleine. Vielmehr handelt es sich um das gesetzte Bit 6 in der ANTIC-Zeile.

Bei Grafik 0 mit LMS also $42 gefolgt von der Speicheradresse. Oder irre ich mich?

CU, Erhard

Jede Info, die zu Hause auf meinem Rechner liegt habe ich unterwegs nicht verfügbar. Jede Info, die im Netz liegt finde ich nicht wieder, wenn ich sie benötige.

... ja klar ... habe ich etwas weiter unten erklärt!

Ich möchte mich an dieser Stelle nochmal bei allen bedanken, ihr seid echt TOP !! Leider ist es alles andere als selbstverständlich das man Fehler machen und fragen kann ohne gleich beschimpft und ausgelacht zu werden. Klasse, weiter so! Ich betreibe selbst mehrere Foren wo ich es auch so handhabe, aber die große Anzahl ist eben, anders...

Nun zurück zum Thema. Dank Eurer Hilfe sind mir nun einige Dinge klar geworden und ich konnte dieses Mini DLIST Programm erstellen:

SDLSTL=$D402
SDLSTH=$D403

    org $2000

start   
    lda #$4a
    sta COLBK

    lda #<dlist
    sta SDLSTL
    lda #>dlist
    sta SDLSTH

endless jmp endless

dlist   .byte $70, $70, $70 ; 24 blank lines on top
    .byte $42, <screen, >screen
    .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
    .byte $41, <dlist, >dlist

screen  .byte "A", "B", "C"

dlist_out.png

Beim "screen" habe ich etwas geschummelt und nur drei ASCII-Zeichen angegeben weil ich einfach davon ausgehe das der Rest 00 ist. Dazu meine Frage: Man kann beim MADS doch sicher über ein Makro einen Speicherbereich initialisieren, sowas wie $00 * 24 * 40 ?

Auch frage ich mich warum die Hintergrundfarbe scheinbar ignoriert wird? Ich hätte erwartet das das sogar für die BLANK lines gilt?

Anhänge:

Thema Hintergrundfarbe:

Du hast colbk nicht definiert. endless jmp endless geht einfacher: jmp * alles andere kann man so machen!

Wieso auslachen? Wir haben alle so angefangen und es ist echt komplex am Anfang... weiter so!!

Ah, jetzt kann man es mit MADS Marko-Befehlen beliebig unleserlich machen 😂 Also, anstelle

    .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2

könnte man die Arbeit den Assembler machen lassen:

    :23 .byte $02

Das ":23" gibt an, das das nachfolgende 23mal wiederholt wird.

Auch eine Möglichkeit die DLIST-Befehle als Variablen binär anzugeben:

dl_blank = %01110000 ; 8 blank lines in background-color

oder vordefinierte Konstanten mit "|" binär ODER verknüpfen.

Raus könnte dann sowas kommen:

dl_gr0   = %00000010 ; graphics mode 0
dl_blank = %01110000 ; 8 blank lines in background-color
dl_jmp   = %10000001 ; JMP
dl_lms   = %01000000 ;

dlist   .byte dl_blank, dl_blank, dl_blank ; 24 blank lines on top
    .byte dl_lms | dl_gr0, <screen, >screen
    :23 .byte dl_gr0
    .byte dl_jmp, <dlist, >dlist

screen  .byte "A", "B", "C"
    :960-3 .byte " "

Dr. Irata schrieb: Du hast colbk nicht definiert.

Ja, ich habe mir eine Include-Datei mit den Registern gemacht die ich immer wieder her nehme. Für die Beispiele hier habe ich die Werte in die Listings gepackt, damit jemand das direkt verwenden kann. Den COLBK habe ich vergessen anzugeben, aber er ist definiert gewesen:

COLBK   = $d01a ; background color

Hier habe ich hier wieder den Shadow-Fehler gemacht, also geändert:

SCOLBK  = $02c8 ; shadow register

und ich habe eine Farbe: dlist_out_colbk.png

Anhänge:

yup - hast du 😉

Noch ein kleiner Hinweis...

Wenn man Hex-Werte eingeben möchte, geht das auch mit der Direktive:

   .he 70 42

Hier hätten wir dann einmal 8 Leerzeilen und dann ein LMS+Gfx 0. Nach dem LMS dann noch:

   .wo screen

und es wird noch leserlicher. .wo und .by kann man in MADS (meist) statt .word und .byte nutzen.

Edit: Noch eine Sache für die Lesbarkeit... die :Anzahl Direktive für die Wiederholungen kann man auch ganz am Anfang der Zeile schreiben, dann sieht man einfacher, was im Rest so gem8 wird...

DL
:3    .he 70
      .he 42
      .wo screen
:23   .he 02
      .he 41
      .wo DL

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

Nun, da ich Buchstaben auf den Bildschirm zaubern kann, gelüstet mich nach mehr 🙂 Will mal etwas mit Farben rumspielen, aber vor allem das Scrolling finde ich spannend. Ich würde mir jetzt einen horizontalen Shooter/Jump'n'Run vorstellen wo ein Player durch eine Landschaft düst. Diese würde ich erstmal einfach durch ASCII-Zeichen simulieren. Muss ich immer den gesamten Bildschirm scrollen, oder geht das auch Zeilenweise? Ich hab so viele Fragen... aber fangen wir mal klein an

Mein Start war so ähnlich wie bei dir - allerdings hatte ich gleich nach kurzer Einarbeitung ein klares Ziel: ich wollte den Vertikalshooter Phobos nachprogrammieren, was ich letztlich auch tat: Battle of Eris - das Jahr danach war dann Teil 2 dran, Caverns of Eris (kannst du dir mal bei youtube anschauen)... alles ist möglich und es macht riesig Spass... wirklich toll und aufregend für dich!!

Du kannst natürlich kleinere Bereiche des Bildschirmes einfach umkopieren... bei richtiger Wahl der Auflösung und des Bildschirmes geht das auch recht flüssig. Bei Caverns of Eris arbeite ich zB komplett ohne Atari-Scrolling, da nutze ich Softwaresprites...

Das ist eine gute Idee, der werde ich folgen. Das mache ich aber in einem neuen Thread.

yMoreT8 schrieb: Muss ich immer den gesamten Bildschirm scrollen, oder geht das auch Zeilenweise? Ich hab so viele Fragen... aber fangen wir mal klein an

Du kannst jede Zeile unabhängig scrollen ohne die Bildschirmdaten tatsächlich zu bewegen ; ANTIC und der Display List sei Dank.

Ein super Tutorial in Englisch findest du hier : https://playermissile.com/scrolling_tutorial/index.html

Rob hat auch eines zu DLIs verfasst, die dir noch mehr Möglichkeiten zum Zaubern auf dem Bildschirm geben.

yMoreT8 schrieb: Makro einen Speicherbereich initialisieren, sowas wie $00 * 24 * 40 ?

Das liest sich zwar sehr kurz, würde aber in einer Porgrammdatei 960 Bytes belegen. Und nicht nur das. Der Speicher würde nur einmalig beim Laden der Datei initialisiert.

Wenn er im Verlauf des Programms erneut auf einen bestimmten Wert gesetzt werden muß geht das nicht, wenn kein Programmcode da ist, der das macht.

LDX #0
TXA
LOOP STA MEMORY,X
STA MEMORY+$100,X
STA MEMORY+$200,X
STA MEMORY+$300,X
DEX
BNE LOOP
RTS

Keine Ahnung ob der Code optimal ist.

Man könnte auch gleich eine Routine schreiben, die einen beliebigen Speicherbereich (von-bis oder von+länge) mit einem beliebigen Wert füllt und diese Route dann mit Parametern aufrufen.

CU, Erhard

Jede Info, die zu Hause auf meinem Rechner liegt habe ich unterwegs nicht verfügbar. Jede Info, die im Netz liegt finde ich nicht wieder, wenn ich sie benötige.